'use client';

import React, { useEffect, useRef, useState } from 'react';

export interface IntersectionObserverProps {
  className?: string;
  /**
   * 用作视口交叉的元素，用于检查目标的可见性。必须是目标的祖先。如果未指定或为 null，则默认为浏览器视口。
   */
  root?: IntersectionObserverInit['root'];
  /**
   * 交叉的阈值 0-1
   * - 默认值为 0（这意味着只要有一个像素可见，回调就会运行）。值为 1.0 意味着在每个像素都可见之前，阈值不会被认为已通过
   * @default 0
   */
  threshold?: IntersectionObserverInit['threshold'];
  /**
   * root 视口周围的边距，用于增大或缩小视口的范围，以影响计算交叉点范围
   */
  rootMargin?: IntersectionObserverInit['rootMargin'];
  /**
   * 指定渲染的 HTML 元素类型
   * @default 'section'
   * @example 'div', 'section', 'article', etc.
   */
  as?: keyof HTMLElementTagNameMap;
  /**
   * 区域宽度
   */
  width: number;
  /**
   * 区域高度
   */
  height: number;
  /**
   * 子元素渲染函数
   * @param isIntersecting - 是否与视口相交
   */
  children?: (isIntersecting: boolean) => React.ReactNode;
}

function IntersectionObserverNoMemoized(props: IntersectionObserverProps) {
  const {
    className,
    root,
    threshold = 0,
    rootMargin,
    as = 'section',
    width,
    height,
    children,
  } = props;

  const targetRef = useRef<HTMLElement>(null);
  const [isIntersecting, setIsIntersecting] = useState(false);

  useEffect(() => {
    const observer = new window.IntersectionObserver(
      (entries) => {
        entries.forEach((entry) => {
          setIsIntersecting(entry.isIntersecting);
        });
      },
      { root, rootMargin, threshold }
    );
    if (targetRef.current) {
      observer.observe(targetRef.current);
    }
    return () => {
      observer.disconnect();
    };
  }, [root, rootMargin, threshold]);

  return React.createElement(
    as,
    {
      className,
      ref: targetRef,
      style: { width, height },
    },
    children?.(isIntersecting)
  );
}

export const IntersectionObserver = React.memo(IntersectionObserverNoMemoized);
